package card.app;

import card.constant.Command;
import card.context.BaseContext;
import card.context.PlatformContext;
import card.manager.PlatformManager;
import card.player.PlayerGeneral;
import card.player.PlayerModel;
import card.rule.CardNumRule;
import card.rule.RuleFactory;
import org.apache.commons.lang3.StringUtils;

import java.util.Scanner;

/**
 * @description: 游戏入口
 * @author: ly
 * @date: 2020/8/20 19:10
 */
public class CardApp implements App {

    @Override
    public void start() throws Exception {
        //游戏界面打印
        printAppInfo();

        //游戏规则打印
        printAppRule();

        //平台初始化，洗牌，注册容器
        PlatformManager manager = (PlatformManager) PlatformManager.build().cardInit().shuffle().register(new PlatformContext());

        //开始发牌
        manager.giveCards(PlayerGeneral.general("小明"), PlayerGeneral.general("小帅"), PlayerGeneral.general("小王"));

        //平台发牌校验
        RuleFactory.create(CardNumRule.class).checkCardNum(manager);

        //开始抢地主
        grabDiZhu(manager);

        //轮番出牌
        roundLeave(manager);
    }

    private void roundLeave(PlatformManager manager) throws Exception {
        //地主玩家开始出牌
        PlayerModel player = manager.getPlayer(BaseContext.getContext().getDiZhuId());
        //设置当前出牌玩家
        PlayerModel currPlayer;
        while (true) {
            currPlayer = StringUtils.isBlank(BaseContext.getContext().getCurrId()) ? player : manager.getNextPlayer();
            //打印提示信息
            printNoticeInfo(manager, currPlayer);
            Scanner scanner = new Scanner(System.in);
            String cards = scanner.nextLine();
            //出牌
            if (!currPlayer.leave(cards)) {
                continue;
            }
            //是否已经出完
            if (currPlayer.getCardList().size() == 0) {
                manager.settle(currPlayer);
                break;
            }
            BaseContext.getContext().setCurrId(currPlayer.getId());
            //必须放到这里，否则容易清屏多度
            this.cleanConsole();
        }
        retryGame();
    }

    private void printNoticeInfo(PlatformManager manager, PlayerModel currPlayer) {
        //预获取下一个玩家,重要
        String currId = BaseContext.getContext().getCurrId();
        BaseContext.getContext().setCurrId(currPlayer.getId());

        System.out.println("轮到玩家：" + currPlayer.getId() + "[" + currPlayer.getMark() + "]" + " 出牌" + " ===>" + currPlayer.order(currPlayer.getCardList()));
        System.out.println("提示：要不起请输入命令[pass],否则直接输入要打出的牌，多个请用空格分隔");
        if (StringUtils.isNotBlank(BaseContext.getContext().getPreId())) {
            System.out.println("提示：上一个玩家是 " + BaseContext.getContext().getPreId() +
                    "[" + BaseContext.getContext().getPreMark() + "]" + " 打出的牌[" + BaseContext.getContext().getPreGiveCards() + "]" +
                    " 下一轮玩家 " + manager.getNextPlayer().getId() + "[" + manager.getNextPlayer().getMark() + "]");
        }
        //设置回去,重要
        BaseContext.getContext().setCurrId(currId);
    }

    private void grabDiZhu(PlatformManager manager) throws Exception {
        //随机获取一个玩家
        PlayerModel randomPlayer = manager.getRandomPlayer();
        //第一个玩家id
        String firstId = randomPlayer.getId();
        //打印玩家信息
        randomPlayer.print();
        //设置当前玩家标识
        BaseContext.getContext().setCurrId(randomPlayer.getId());
        //设置当前玩家
        PlayerModel currPlayer = null;
        while (true) {
            System.out.println("***开始抢地主 命令[yes/no]***");
            Scanner scanner = new Scanner(System.in);
            String command = scanner.nextLine();
            if (!command.equalsIgnoreCase(Command.YES) && !command.equalsIgnoreCase(Command.NO)) {
                System.out.println("!!!请输入正确的命令[yes/no]!!!");
                continue;
            }
            if (command.equalsIgnoreCase(Command.YES)) {
                if (currPlayer == null) {
                    currPlayer = randomPlayer;
                }
                //设置地主标识
                currPlayer.setDiZhu(true);
                break;
            } else {
                //获取下一个玩家
                currPlayer = manager.getNextPlayerRound(firstId);
                if (currPlayer == null) {
                    break;
                }
                //打印玩家信息
                currPlayer.print();
                //设置当前玩家标识
                BaseContext.getContext().setCurrId(currPlayer.getId());
            }
        }

        //是否抢地主成功
        if (currPlayer != null && currPlayer.isDiZhu()) {
            grabSucc(manager, currPlayer);
        } else {
            grabFail();
        }
    }

    /**
     * 抢地主成功
     *
     * @param manager    平台管理器
     * @param currPlayer 玩家
     */
    private void grabSucc(PlatformManager manager, PlayerModel currPlayer) {
        System.out.println("恭喜你，抢地主成功！");
        System.out.println("===========================================================");
        BaseContext.init();
        BaseContext.getContext().setDiZhuId(currPlayer.getId());
        //将底牌给当前玩家
        currPlayer.getCardList().addAll(manager.getBottom());
    }

    /**
     * 抢地主失败
     *
     * @throws Exception 异常
     */
    private void grabFail() throws Exception {
        //抢地主失败
        System.out.println("！没有人抢地主，是否重启游戏？[yes/no]");
        startOrFinished();
    }

    /**
     * 重启游戏
     *
     * @throws Exception 异常
     */
    private void retryGame() throws Exception {
        //抢地主失败
        System.out.println("是否再来一局？[yes/no]");
        startOrFinished();
    }

    /**
     * 开始或结束
     *
     * @throws Exception 异常
     */
    private void startOrFinished() throws Exception {
        Scanner scanner = new Scanner(System.in);
        String command = scanner.nextLine();
        if (command.equalsIgnoreCase(Command.YES)) {
            start();
        } else {
            finished();
        }
    }

    /**
     * 打印游戏规则
     *
     * @throws InterruptedException 异常
     */
    private void printAppRule() throws InterruptedException {
        System.out.println("=============================开始介绍游戏规则===================================");
        System.out.println("本次游戏为三人局，包含抢地主，每人起手17张牌，底牌三张，地主可以拿到剩余底牌...");
        Thread.sleep(1000);
        System.out.println("每个玩家可以出单张,一对,三连张,三带一,三带二,顺子，连对，飞机，炸弹，王炸等牌型...");
        Thread.sleep(1000);
        System.out.println("每个玩家出的牌如果有多张，必须用空格分离...");
        Thread.sleep(1000);
        System.out.println("当上一个玩家打出牌后，下家可以根据提示选择相应命令或者打出对应牌型的牌...");
        Thread.sleep(1000);
        System.out.println("王炸>4张炸弹>其他...");
        System.out.println("=================================================================================");
        Thread.sleep(1000);
        System.out.println("游戏启动中，请稍等...");
        Thread.sleep(3000);
    }

    /**
     * 打印界面
     *
     * @throws InterruptedException 异常
     */
    private void printAppInfo() throws InterruptedException {
        System.out.println("***********************欢迎进入小Y斗地主,祝您游戏体验愉快**********************");
        Thread.sleep(1000);
    }

    @Override
    public void finished() {
        System.out.println("******游戏结束******");
        System.exit(1);
    }

    @Override
    public void cleanConsole() {
        for (int i = 0; i < 20; i++) {
            System.out.println();
        }
    }
}
